package cn.lili.modules.verification;

import cn.lili.common.utils.Base64DecodeMultipartFile;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.SerializableStream;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Base64Utils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

/**
 * 验证码工具
 *
 * @author Chopper
 * @version v4.0
 * @since 2020/11/17 14:34
 */
@Slf4j
public class SliderImageUtil {

	private static final int BOLD = 5;

	private static final String IMG_FILE_TYPE = "jpg";

	private static final String TEMP_IMG_FILE_TYPE = "png";

	/**
	 * 根据模板切图
	 *
	 * @param sliderFile
	 *            滑块
	 * @param originalFile
	 *            原图
	 * @param watermark
	 *            水印
	 * @param interfereNum
	 *            干扰选项
	 * @return 滑块参数
	 * @throws Exception
	 *             sliderFile, originalFile
	 */
	public static Map<String, Object> pictureTemplatesCut(SerializableStream sliderFile,
			SerializableStream interfereSliderFile, SerializableStream originalFile, String watermark,
			Integer interfereNum) throws Exception {

		Random random = new Random();
		Map<String, Object> pictureMap = new HashMap<>(16);
		// 拼图
		BufferedImage sliderImage = ImageIO.read(Base64DecodeMultipartFile.base64ToInputStream(sliderFile.getBase64()));
		int sliderWidth = sliderImage.getWidth();
		int sliderHeight = sliderImage.getHeight();

		// 原图
		BufferedImage originalImage = ImageIO
				.read(Base64DecodeMultipartFile.base64ToInputStream(originalFile.getBase64()));
		int originalWidth = originalImage.getWidth();
		int originalHeight = originalImage.getHeight();

		// 随机生成抠图坐标X,Y
		// X轴距离右端targetWidth Y轴距离底部targetHeight以上
		int randomX = random.nextInt(originalWidth - 3 * sliderWidth) + 2 * sliderWidth;
		int randomY = random.nextInt(originalHeight - sliderHeight);
		log.info("原图大小{} x {},随机生成的坐标 X,Y 为（{}，{}）", originalWidth, originalHeight, randomX, randomY);

		// 新建一个和模板一样大小的图像，TYPE_4BYTE_ABGR表示具有8位RGBA颜色分量的图像，正常取imageTemplate.getType()
		BufferedImage newImage = new BufferedImage(sliderWidth, sliderHeight, sliderImage.getType());
		// 得到画笔对象
		Graphics2D graphics = newImage.createGraphics();
		// 如果需要生成RGB格式，需要做如下配置,Transparency 设置透明
		newImage = graphics.getDeviceConfiguration().createCompatibleImage(sliderWidth, sliderHeight,
				Transparency.TRANSLUCENT);

		// 新建的图像根据模板颜色赋值,源图生成遮罩
		ImageUtil.cutByTemplate(originalImage, sliderImage, newImage, randomX, randomY);

		// 干扰项
		if (interfereNum > 0) {
			BufferedImage interfereSliderImage = ImageIO
					.read(Base64DecodeMultipartFile.base64ToInputStream(interfereSliderFile.getBase64()));
			for (int i = 0; i < interfereNum; i++) {
				int interfereX = random.nextInt(originalWidth - 3 * sliderWidth) + 2 * sliderWidth;
				int interfereY = random.nextInt(originalHeight - sliderHeight);
				ImageUtil.interfereTemplate(originalImage, interfereSliderImage, interfereX, interfereY);
			}
		}

		// 设置“抗锯齿”的属性
		graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
		graphics.setStroke(new BasicStroke(BOLD, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL));
		graphics.drawImage(newImage, 0, 0, null);
		graphics.dispose();

		// 添加水印
		if (StringUtils.isNotEmpty(watermark)) {
			ImageUtil.addWatermark(originalImage, watermark);
		}
		// 新建流
		ByteArrayOutputStream newImageOs = new ByteArrayOutputStream();
		// 利用ImageIO类提供的write方法，将bi以png图片的数据模式写入流。
		ImageIO.write(newImage, TEMP_IMG_FILE_TYPE, newImageOs);
		byte[] newImagery = newImageOs.toByteArray();
		// 新建流
		ByteArrayOutputStream oriImagesOs = new ByteArrayOutputStream();
		// 利用ImageIO类提供的write方法，将bi以jpg图片的数据模式写入流
		ImageIO.write(originalImage, IMG_FILE_TYPE, oriImagesOs);
		byte[] oriImageByte = oriImagesOs.toByteArray();

		pictureMap.put("slidingImage", "data:image/png;base64," + Base64Utils.encodeToString(newImagery));
		pictureMap.put("backImage", "data:image/png;base64," + Base64Utils.encodeToString(oriImageByte));
		// x轴
		pictureMap.put("randomX", randomX);
		// y轴
		pictureMap.put("randomY", randomY);

		pictureMap.put("originalHeight", originalHeight);
		pictureMap.put("originalWidth", originalWidth);
		pictureMap.put("sliderHeight", sliderHeight);
		pictureMap.put("sliderWidth", sliderWidth);
		return pictureMap;
	}

}
